package Metier;



import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Scanner;

import javax.imageio.ImageIO;
import javax.swing.text.StyledDocument;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;

import org.jdom.Comment;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.ProcessingInstruction;
import org.jdom.Text;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;

/**
 * Classe de gestion des pages
 * @author Aubry Thomas
 * @author Bouchet Sylvain
 * @author Fauvel Alexis
 * @author Lessieur Jocelyn
 * @author Mathias Bastien 
 * @author Teuf Antoine
 * @version 1.0
 */

public class Page extends Element {
	
	/**
	 * nom du projet auquel appartient la page
	 * @see Page#getNomProjet()
	 */
	private String nomProjet;
	
	/**
	 * nom du fichier dans lequel sera enregistrer la page
	 * @see Page#setNomFichier(String)
	 * @see Page#getNomFichier()
	 */
	private String nomFichier="";
	
	/**
	 * element titre de la page
	 * @see Page#getTitrePage()
	 * @see Page#setTitrePage(String)
	 */
	private Element titrePage;

	/**
	 * Document contenant la page
	 */
	private Document document;
	
	/**
	 * Projet auquel appartient la page
	 * @see Page#getProjet()
	 */
	private Projet projet;
	
	/**
	 * nom de la racine de la page
	 */
	private String racine;

	/**
	 * Constructeur de la classe Page
	 * @param racine		Racine de la page
	 * @param titrePage		titre de la page
	 * @param projet		Nom du projet auquel s'ajoute la page	
	 */
	public Page(String racine, String titrePage, Projet projet) {
		super("page");
		this.racine = racine;
		ProcessingInstruction xsl;
		
		this.projet=projet;
		nomProjet = projet.getNom();
		document = new Document();

		xsl = new ProcessingInstruction("xml-stylesheet",
				"type='text/xsl' href='defaut.xsl'");
		
		TransformerFactory f = TransformerFactory.newInstance();
		Transformer trans;
		
		try{
			trans = f.newTransformer();
			trans.setParameter("projet",nomProjet);
		}catch (Exception e) {
			// TODO: handle exception
		}
		document.addContent(xsl);

		document.addContent(this);

		this.titrePage = new Element("titrePage");
		this.titrePage.setText(titrePage);
		addContent(this.titrePage);
		addContent(new Text(""));
	}
	
	/**
	 * Permet de modifier le nom du fichier dans lequel est enregistré la page
	 * @param nomfichier	nouveau nom du fichier
	 */
	public void setNomFichier(String nomfichier){
		this.nomFichier=nomFichier;
	}
	

	/**
	 * Permet d'obtenir le nom du fichier dans lequel est enregistré la page
	 * @return	nom du fichier sous forme de string
	 */
	public String getNomFichier(){
		return nomFichier;
	}
	
	/**
	 * Permet de modifier le projet par un autre
	 * @param p	nouveau Projet à lier à la page
	 */
	public void setProjet(Projet p){
		projet=p;
		nomProjet=p.getNom();
	}

	/**
	 * Permet de modifier le titre de la page
	 * @param t	nouveau titre de la page
	 */
	public void modifTitrePage(String t) {
		removeContent(titrePage);
		titrePage.setText(t);
		addContent(0, titrePage);
	}

	/***
	 * Permet d'inserer un titre à la page
	 * @param t	nom du titre à inserer
	 */
	public void insererTitre(String t) {
		addContent(new Titre(t));
		addContent(new Text(""));
	}

	/***
	 * Permet d'inserer un sous titre à la page
	 * @param t	nom du sous titre à inserer
	 */
	public void insererSousTitre(String t) {
		addContent(new SousTitre(t));
		addContent(new Text(""));
	}
	
	/**
	 * Permet d'inserer un paragraphe à la page depuis un StyledDocument
	 * @param style	StyledDocument à ajouter à la page
	 */
	public void insererParagraphe(StyledDocument style) {
		addContent(new Paragraphe(style));
		addContent(new Text(""));
	}
	
	/**
	 * Permet d'inserer un commentaire à la page
	 * @param c	contenu du commentaire
	 */
	public void insererCommentaire(String c) {
		Comment co = new Comment(c);
		addContent(co);
	}

	/**
	 * Permet d'inserer une image à la page
	 * @param chemin	chemin d'accès de l'image 
	 */
	public void insererImage(String chemin) {
        File fichier = new File(chemin);
        String nom=fichier.getName();
        
        
        File fImage=new File(racine + nomProjet + "/images/"+nom);
        int i=1;
        while(fImage.exists()){
			int index=nom.lastIndexOf(".");
			if(index>=0){
				if(nom.matches("^.*\\([1-9]\\)\\..*$"))
					nom=nom.substring(0, index-3)+"("+i+")"+nom.substring(index);
				else if(nom.matches("^.*\\([1-9][0-9]\\)\\..*$"))
					nom=nom.substring(0, index-4)+"("+i+")"+nom.substring(index);
				else
				nom=nom.substring(0, index)+"("+i+")"+nom.substring(index);
			}
			else{
				if(nom.matches("^.*\\([1-9]\\)*$"))
					nom=nom.substring(0, index-3)+"("+i+")"+nom.substring(index);
				else if(nom.matches("^.*\\([10-99]\\)*$"))
					nom=nom.substring(0, index-4)+"("+i+")"+nom.substring(index);
				else
					nom+="("+i+")";
			}
        	fImage=new File(racine + nomProjet + "/images/"+nom);
        	i++;
        }
        copier(chemin, "images/" + nom);
        
        Image image = new Image(nom);
        addContent(image);
        addContent(new Text(""));
	}

	/**
	 * Permet d'inserer un lien vers un site à la page
	 * @param intitule	nom du lien
	 * @param lien		URL du lien internet à ajouter
	 */
	public void insererLien(String intitule, String lien) {
		addContent(new Lien(intitule, lien));
		addContent(new Text(""));
	}
	
	/**
	 * Permet d'inserer un lien vers un fichier à la page 
	 * @param intitule	nom du lien
	 * @param fichier	URL du fichier à ajouter
	 */
	public void insererLien(String intitule, File fichier) {
		File sortie = new File(racine+nomProjet+"/ressources/"+fichier.getName());
		File fichier2=new File(fichier.getName());
		int i=1;
		String nomLien=fichier.getName();
		
		while(sortie.exists()){
			int index=nomLien.lastIndexOf(".");
			if(index>=0){
				if(nomLien.matches("^.*\\([1-9]\\)\\..*$"))
					nomLien=nomLien.substring(0, index-3)+"("+i+")"+nomLien.substring(index);
				else if(nomLien.matches("^.*\\([1-9][0-9]\\)\\..*$"))
					nomLien=nomLien.substring(0, index-4)+"("+i+")"+nomLien.substring(index);
				else
					nomLien=nomLien.substring(0, index)+"("+i+")"+nomLien.substring(index);
			}
			else{
				if(nomLien.matches("^.*\\([1-9]\\)*$"))
					nomLien=nomLien.substring(0, index-3)+"("+i+")"+nomLien.substring(index);
				else if(nomLien.matches("^.*\\([10-99]\\)*$"))
					nomLien=nomLien.substring(0, index-4)+"("+i+")"+nomLien.substring(index);
				else
					nomLien+="("+i+")";
			}
			sortie = new File(racine+nomProjet+"/ressources/"+nomLien);
			i++;
		}
		
		
		if(!sortie.getParentFile().exists())
			sortie.getParentFile().mkdirs();
		
		FileChannel in = null; // canal d'entrÃ©e
		FileChannel out = null; // canal de sortie
		 
		try {
		  in = new FileInputStream(fichier).getChannel();
		  out = new FileOutputStream(sortie).getChannel();
		 
		  in.transferTo(0, in.size(), out);
		} catch (Exception e) {
		  e.printStackTrace();
		} finally {
		  if(in != null) {
		  	try {
			  in.close();
			} catch (IOException e) {}
		  }
		  if(out != null) {
		  	try {
			  out.close();
			} catch (IOException e) {}
		  }
		}
		addContent(new Lien(intitule, "ressources/"+nomLien));
		addContent(new Text(""));
		
	}

	/**
	 * Permet d'enregistrer la page dans un fichier
	 * @param fichier	nom du fichier
	 */
	public void enregistre(String fichier) {
		nomFichier = fichier;//Stock le nom de la page comme nom de fichier.
		Format fo = Format.getRawFormat();
		fo.setIndent("\t");
		fo.setLineSeparator("\n");
		File f = new File(racine + nomProjet, fichier + ".xml");

		try {
			XMLOutputter sortie = new XMLOutputter(fo);
			sortie.output(document, new FileOutputStream(f));
		} catch (java.io.IOException e) {
			System.out.println(e);
		}
		
		new Sommaire(racine, projet);
		new StyleCSS(racine, projet);
		
		miseEnPage(f);
		justification(f);
	}
	
	/**
	 * Permet d'effectuer une mise en page du fichier
	 * @param f	fichier a mettre en page
	 */
	public void miseEnPage(File f){
		boolean dansParagraphe=false;
		String texte="";
		try{
			InputStream ips=new FileInputStream(f);
			InputStreamReader ipsr=new InputStreamReader(ips);
			BufferedReader br=new BufferedReader(ipsr);
			String ligne;
			while ((ligne=br.readLine())!=null){
				if(ligne.contains("</paragraphe>"))	dansParagraphe=false;
				
				if(ligne.contains("<titrePage>")){
					texte+="\n"+"\t<!-- - - - - - - - - - -->\n"
							   +"\t<!-- Titre de la page  -->\n"
							   +"\t<!-- - - - - - - - - - -->\n\n";
				}
				else if(ligne.contains("<titre>")){
					texte+="\n"+"\t<!-- - - - - - - - - - -->\n"
							   +"\t<!--       Titre       -->\n"
							   +"\t<!-- - - - - - - - - - -->\n\n";
				}
				else if(ligne.contains("<ssTitre>")){
					texte+="\n"+"\t<!-- - - - - - - - - - -->\n"
							   +"\t<!--     Sous-Titre    -->\n"
							   +"\t<!-- - - - - - - - - - -->\n\n";
				}
				else if(ligne.contains("<image>")){
					texte+="\n"+"\t<!-- - - - - - - - - - -->\n"
							   +"\t<!--       Image       -->\n"
							   +"\t<!-- - - - - - - - - - -->\n\n";
				}
				else if(ligne.contains("<paragraphe>")){
					texte+="\n"+"\t<!-- - - - - - - - - - -->\n"
							   +"\t<!--    Paragraphe     -->\n"
							   +"\t<!-- - - - - - - - - - -->\n\n";
				}
				else if(ligne.contains("<lien")){
					texte+="\n"+"\t<!-- - - - - - - - - - -->\n"
							   +"\t<!--       Lien        -->\n"
							   +"\t<!-- - - - - - - - - - -->\n\n";
				}
				
				if(ligne.contains("<g>") || ligne.contains("</g>")
				|| ligne.contains("<i>") || ligne.contains("</i>")
				|| ligne.contains("<b>") || ligne.contains("</b>")
				|| ligne.contains("<s>") || ligne.contains("</s>")){
					String[] tab=ligne.split("\t");
					for(int i=0;i<tab.length;i++){
						if(tab[i].isEmpty())
							continue;
						else{
							if(texte.substring(texte.length()-1, texte.length()).equals("\n"))
								texte+="\t\t\t"+tab[i];
							else
								texte+=tab[i];
						}
					}
				}
				else if((ligne.contains("<br />") ||ligne.contains("</align-centre>") || ligne.contains("</align-gauche>") || ligne.contains("</align-droite>") || ligne.contains("</align-justifie>")) && !(ligne.contains("<align-centre>") || ligne.contains("<align-gauche>") || ligne.contains("<align-droite>") || ligne.contains("<align-justifie>"))){
					if(texte.substring(texte.length()-1, texte.length()).equals("\n"))
						texte+=ligne+"\n";
					else
						texte+="\n"+ligne+"\n";
				}
				else{
					if(dansParagraphe && !(ligne.contains("<align-centre>") || ligne.contains("<align-gauche>") || ligne.contains("<align-droite>") || ligne.contains("<align-justifie>"))){
						String[] tab=ligne.split("\t");
						for(int i=0;i<tab.length;i++){
							if(tab[i].isEmpty())
								continue;
							else{
								if(texte.substring(texte.length()-1, texte.length()).equals("\n"))
									texte+="\t\t\t"+tab[i];
								else
									texte+=tab[i];
							}
						}
					}
					else if((ligne.contains("<align-centre>") || ligne.contains("<align-gauche>") || ligne.contains("<align-droite>") || ligne.contains("<align-justifie>")) && ligne.indexOf(">")+1!=ligne.length()){
						texte+=ligne.substring(0,ligne.indexOf(">")+1)+"\n";
						texte+="\t\t\t"+ligne.substring(ligne.indexOf(">")+1,ligne.lastIndexOf("<"))+"\n";
						texte+="\t\t"+ligne.substring(ligne.lastIndexOf("<"))+"\n";
					}
					else{
						texte+=ligne+"\n";
					}
				}
				
				if(ligne.contains("<paragraphe>"))	dansParagraphe=true;
			}
			br.close(); 
		}		
		catch (Exception e){
			System.out.println(e.toString());
		}
		
		if(f.exists())
			f.delete();
		try
		{
			FileWriter fw = new FileWriter(f);
			BufferedWriter output = new BufferedWriter(fw);
			
			output.write(texte);
			output.flush();
			output.close();
		}
		catch(IOException ioe){
			System.out.print("Erreur : ");
			ioe.printStackTrace();
		}	
	}

	/**
	 * Permet la copie d'une image vers une destination donnée dans le projet
	 * @param source		nom de l'image à copier
	 * @param destination	nom du l'image de destination
	 */
	public void copier(String source, String destination) {

		FileChannel in = null; // canal d'entrée
		FileChannel out = null; // canal de sortie

		try {
			File root = new File(racine + nomProjet + "/images/");
			if (!root.exists())
				root.mkdirs();
			// Init
			in = new FileInputStream(source).getChannel();
			out = new FileOutputStream(racine + nomProjet + "/"
					+ destination).getChannel();

			// Copie depuis le in vers le out
			in.transferTo(0, in.size(), out);
		} catch (Exception e) {
			e.printStackTrace(); // n'importe quelle exception
		} finally { // finalement on ferme
			if (in != null) {
				try {
					in.close();
				} catch (IOException e) {
				}
			}
			if (out != null) {
				try {
					out.close();
				} catch (IOException e) {
				}
			}
		}

	}
	
	/**
	 * Permet de recuperer les elements de la page sous forme d'arraylist
	 * @return	Une Arraylist contenant tout les elements de la page
	 */
	public ArrayList<Element> getElementsPage() {
		ArrayList<Element> al = new ArrayList<Element>();

		Iterator<Page> it = getChildren().iterator();
		while (it.hasNext()) {
			al.add(it.next());
		}
		return al;
	}

	/**
	 * Permet de recuperer le nom du projet
	 * @return le nom du projet sous un string
	 */
	public String getNomProjet() {
		return nomProjet;
	}
	
	/**
	 * Permet de recuperer le projet
	 * @return le projet en cours 
	 */
	public Projet getProjet(){
		return projet;
	}

	/**
	 * Permet d'obtenir le titre de la page
	 * @return	le titre dans un string
	 */
	public String getTitrePage() {
		return titrePage.getValue();
	}
	
	/**
	 * Permet de modifier le titre de la page
	 * @param titre	nouveau titre de la page
	 */
	public void setTitrePage(String titre) {
		this.titrePage.setText(titre);
	}

	/**
	 * Permet d'afficher le contenu de l'element page courant
	 * @return contenu de l'element sous forme d'un String
	 */
	public String toString() {
		return titrePage.getText();
	}

	/**
	 * Permet de justifier les paragraphes dans les fichiers generés
	 * Augmente la lisibilité du code source generé
	 * @param f
	 */
	public void justification(File f){
		boolean dansParagraphe=false;
		String texte="";
		try{
			InputStream ips=new FileInputStream(f);
			InputStreamReader ipsr=new InputStreamReader(ips);
			BufferedReader br=new BufferedReader(ipsr);
			String ligne;
			while ((ligne=br.readLine())!=null){
				if(ligne.contains("</paragraphe>"))	dansParagraphe=false;
				int nbChar=ligne.length();
				String[]mots=ligne.split(" ");
				if(dansParagraphe && nbChar>100 && mots.length>1){
					ligne=ligne.substring(3);
					mots=ligne.split(" ");
	                String newLigne="";
	                int index=0;
	                for(int i=0;i<mots.length;i++){
	                		if(i==0)
	                			 newLigne+=mots[i];
	                        if((newLigne.length()-index)+mots[i].length()+1<=100){
	                                newLigne+=" "+mots[i];
	                        }
	                        else{
	                                newLigne+="\n"+mots[i];
	                                index=newLigne.lastIndexOf("\n");
	                        }
	                }
	               
	               
	                String[] tabLigne=newLigne.split("\n");
	                String ligneFinie="\t\t\t";
	                for(int i=0;i<tabLigne.length-1;i++){
	                        if(tabLigne[i].length()<100){
	                                String[]mot2=tabLigne[i].split(" ");
	                                int nbEspace=(100-tabLigne[i].length())+mot2.length-1;
	                                int nb=1;
	                                int j=0;
	                                while(nb<=nbEspace){
	                                        mot2[j]+=" ";
	                                        if(j==mot2.length-2){
	                                                j=0;
	                                        }
	                                        else{
	                                                j++;
	                                        }
	                                        nb++;
	                                }
	                                mot2[mot2.length-1]+="\n\t\t\t";
	                                for(String m:mot2){
	                                        ligneFinie+=m;
	                                }
	                        }
	                        else{
	                                ligneFinie+=tabLigne[i]+"\n\t\t\t";
	                        }
	                }
	                ligneFinie+=tabLigne[tabLigne.length-1]+"\n";
	                
					texte+=ligneFinie;
				}
				else{
					texte+=ligne+"\n";
				}
					
				if(ligne.contains("<paragraphe>"))
					dansParagraphe=true;
			}
			br.close(); 
		}		
		catch (Exception e){
			e.printStackTrace();
		}
		
		if(f.exists())
			f.delete();
		try
		{
			FileWriter fw = new FileWriter(f);
			BufferedWriter output = new BufferedWriter(fw);
			
			output.write(texte);
			output.flush();
			output.close();
		}
		catch(IOException ioe){
			System.out.print("Erreur : ");
			ioe.printStackTrace();
		}	
	}
}
